home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-09-29 | 8.1 KB | 339 lines | [TEXT/KAHL] |
- #define min( a, b) (((a) < (b)) ? (a) : (b))
- #define max( a, b) (((a) > (b)) ? (a) : (b))
-
- #include <QuickDraw.h>
-
- #include "C_randomizer.h"
- #include "screenarea.h"
- //
- // 941027: significantly increase 'max_error' to 'pseudo-fix' the bug
- // with Set/Move/EraseMultiDots. This costs us about 40K extra memory
- // per instance of 'screenarea', but what the heck⦠Alternatively we
- // could just allocate one common 'waste_area'.
- //
- // const int screenarea::max_error = 20;
- //
- const int screenarea::max_error = 20000;
-
- screenarea::screenarea( int numbits, screen_position where)
- : size( 1 << numbits)
- , half_size( 1 << (numbits - 1))
- , shiftbits( 2 * numbits - 9)
- , coord_shift( 16 - numbits)
- {
- GDHandle thescreendevice = GetMainDevice();
- const PixMapHandle pix_of_current = (**thescreendevice).gdPMap;
- const Rect screenrect = (**pix_of_current).bounds;
- const int half_screenHeight = (screenrect.bottom - screenrect.top) / 2;
- const int half_screenWidth = (screenrect.right - screenrect.left) / 2;
-
- int ypos = half_screenHeight - half_size;
- int xpos = 0;
-
- switch( where)
- {
- case centered:
- xpos = half_screenWidth - half_size;
- break;
-
- case left_side:
- xpos = half_screenWidth - (size + 48);
- break;
-
- case right_side:
- xpos = half_screenWidth + 48;
- break;
-
- default:
- DebugStr( "\pInvalid position in 'live_flow' constructor");
- }
- init( xpos, ypos);
- }
-
- screenarea::~screenarea()
- {
- screen -= half_size;
- delete screen;
- waste_area -= max_error;
- delete waste_area;
- }
-
- void screenarea::fill( const int value)
- {
- for( int y = -half_size; y < half_size; y++)
- {
- unsigned char *row = screen[ y] - half_size;
- for( int x = 0; x < size; x++)
- {
- *row++ = value;
- }
- }
- }
-
- void screenarea::add_circular_mask( void)
- {
- //
- // We assume colors 0 through 127 to form a nice ramp from white
- // to black and all other colors to be black. That way color 0
- // is white and color 255 is black (as is customary on the Mac)
- // _and_ we can make a perfectly black screen which turns into a
- // grayscale image by adding 0x80 to the pixels.
- //
- // Note: we use (x+1) * (x+1) = x2 + 2 * x + 1 to speed things up
- //
- int y_squared = -half_size * -half_size;
-
- const int square_limit = half_size * half_size;
-
- for( int y = -half_size; y < half_size; y++)
- {
- unsigned char *row = screen[ y];
- int square_sum = y_squared + -half_size * -half_size;
-
- for( int x = -half_size; x < half_size; x++)
- {
- if( square_sum >= square_limit)
- {
- row[ x] = 255; // always stays black
- } else {
- row[ x] = (unsigned char)(0x80 + (square_sum >> shiftbits));
- }
- square_sum += (x << 1) + 1;
- }
- y_squared += (y << 1) + 1;
- }
- }
-
- void screenarea::add_rectangular_mask( int mask_size)
- {
- const int mask_limit = half_size - mask_size;
- //
- // We assume colors 0 through 127 to form a nice ramp from white
- // to black and all other colors to be black. That way color 0
- // is white and color 255 is black (as is customary on the Mac)
- // _and_ we can make a perfectly black screen which turns into a
- // grayscale image by adding 0x80 to the pixels. => write 255
- // to pixels which must stay black at all times, write 128 to
- // pixels which may turn white.
- //
- for( int y = -half_size; y < half_size; y++)
- {
- unsigned char *row = screen[ y];
- const int y_at_outside = (y < -mask_limit) || (y >= mask_limit);
- if( y_at_outside)
- {
- for( int x = -half_size; x < half_size; x++)
- {
- row[ x] = 255;
- }
- } else {
- for( int x = -half_size; x < half_size; x++)
- {
- const int x_at_outside = (x < -mask_limit) || (x >= mask_limit);
- if( x_at_outside)
- {
- row[ x] = 255; // always stays black
- } else {
- row[ x] = 128;
- }
- }
- }
- }
- }
-
- void screenarea::add_fixation_dot( const int disparity)
- {
- add_big_dot( 0, 0, disparity);
- }
-
- void screenarea::add_stereo_cues( const int disparity)
- {
- const int one_q_size = half_size / 2;
-
- add_big_dot( one_q_size, one_q_size, disparity);
- add_big_dot( one_q_size, -one_q_size, disparity);
- add_big_dot( -one_q_size, one_q_size, disparity);
- add_big_dot( -one_q_size, -one_q_size, disparity);
- }
-
- void screenarea::compass2offsets( const char *compass, int *offsets, int *maxnum)
- {
- const int bovengrens = 500;
- int *temp_result = new int[ bovengrens]; // more than enough?
-
- int curoffset = 0;
- int min_offset = 0;
- int max_offset = 0;
- int curindex = 0;
- int numtoset = 0;
- int stepoffset = 0;
- int mark_them = false;
-
- int index = 0;
- while( compass[ index] != 0)
- {
- switch( compass[ index])
- {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- numtoset *= 10;
- numtoset += compass[ index] - '0';
- break;
-
- case 'E':
- mark_them = true;
- case 'e':
- stepoffset = 1;
- break;
-
- case 'S':
- mark_them = true;
- case 's':
- stepoffset = rowBytes;
- break;
-
- case 'W':
- mark_them = true;
- case 'w':
- stepoffset = -1;
- break;
-
- case 'N':
- mark_them = true;
- case 'n':
- stepoffset = -rowBytes;
- break;
-
- case '.':
- numtoset = 1; // replace '3.' by '.' ('3.' doesn't make sense)
- mark_them = true;
- break;
-
- default:
- DebugStr( "\pInvalid character in 'compasses' string");
- }
- if( (stepoffset != 0) || (mark_them == true))
- {
- if( numtoset == 0)
- {
- numtoset = 1;
- }
- if( mark_them)
- {
- mark_them = false;
- for( int i = 0; i < numtoset; i++)
- {
- min_offset = min( curoffset, min_offset);
- max_offset = max( curoffset, max_offset);
- temp_result[ curindex] = curoffset;
- curindex += 1;
- curoffset += stepoffset;
- }
- } else {
- curoffset += numtoset * stepoffset;
- }
- numtoset = 0;
- stepoffset = 0;
- }
- index += 1;
- }
- //
- // We now have computed both the actual number of offsets (in curindex),
- // the actual offsets (in temp_result[ 0] through temp_result[ curindex - 1]),
- // and the range of offsets encountered (in min_offset and max_offset, provided
- // that zero is actually inside the range of offsets encountered).
- //
- if( min_offset <= -max_error)
- {
- DebugStr( "\pscreenarea::compass2offsets : minimal offset too small");
- }
- if( max_offset >= max_error)
- {
- DebugStr( "\pscreenarea::compass2offsets : maximal offset too large");
- }
- if( offsets != 0)
- {
- const int numtocopy = (*maxnum < curindex) ? *maxnum : curindex;
- for( int i = 0; i < numtocopy; i++)
- {
- offsets[ i] = temp_result[ i];
- }
- }
- *maxnum = curindex;
- delete temp_result;
- }
-
- void screenarea::init( int xpos, int ypos)
- {
- screen = new unsigned char *[ size];
- waste_area = new unsigned char[ size + 2 * max_error];
- waste_area += max_error;
-
- GDHandle thescreendevice = GetMainDevice();
- const PixMapHandle pix_of_current = (**thescreendevice).gdPMap;
-
- const Rect screenrect = (**pix_of_current).bounds;
-
- rowBytes = ((**pix_of_current).rowBytes) & 0x1FFF;
-
- const int screenHeight = screenrect.bottom - screenrect.top;
- const int screenWidth = screenrect.right - screenrect.left;
-
- unsigned char *screenBits = (unsigned char *)(**pix_of_current).baseAddr;
- //
- // safety
- //
- if( xpos + size >= screenWidth)
- {
- xpos = screenWidth - size;
- }
- if( xpos < 0)
- {
- xpos = 0;
- }
- for( int i = 0; i < size; i++)
- {
- const int ypos_plus_i = ypos + i;
-
- if( (ypos_plus_i < 0) || (ypos_plus_i >= screenHeight))
- {
- screen[ i] = waste_area;
- } else {
- screen[ i] = screenBits + (ypos_plus_i * rowBytes) + xpos;
- }
- }
- //
- // We have now allocated the array to point at the start of the rows.
- // Change this to point halfway into the rows:
- //
- #ifdef __MWERKS__
- for( int i = 0; i < size; i++)
- #else
- for( i = 0; i < size; i++)
- #endif
- {
- screen[ i] += half_size;
- }
- screen += half_size;
- }
-
- void screenarea::add_big_dot( const int x, const int y, const int disparity)
- {
- const int left_disparity = disparity / 2;
- const int right_disparity = left_disparity - disparity;
-
- unsigned char *screen_y = screen[ y];
-
- screen_y[ x + left_disparity ] -= 1;
- screen_y[ x + right_disparity ] -= 8;
- screen_y[ x + left_disparity + 1] -= 1;
- screen_y[ x + right_disparity + 1] -= 8;
-
- screen_y = screen[ y + 1];
-
- screen_y[ x + left_disparity ] -= 1;
- screen_y[ x + right_disparity ] -= 8;
- screen_y[ x + left_disparity + 1] -= 1;
- screen_y[ x + right_disparity + 1] -= 8;
- }
-